package org.example.socketdemos;

import org.example.utils.LogUtils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;

public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
        // 定义一个注册器实例
        Selector selector = Selector.open();

        // 定义一个接收socket的通道
        ServerSocketChannel serverChannel = ServerSocketChannel.open();

        // 设置非阻塞
        serverChannel.configureBlocking(false);

        // 绑定8080端口
        serverChannel.bind(new InetSocketAddress("localhost", 8081));

        // 注册 接收socket 监听事件
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 开始轮询selector
        while (selector.select() > 0) {
            LogUtils.info("获取监听的事件");
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            for (SelectionKey selectionKey : selectionKeys) {
                if (selectionKey.isAcceptable()) {
                    // 有新连接进来，获取传输通道
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();

                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);

                    LogUtils.info("有新的连接进来");

                    // 注册该通道的读事件
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    // 读数据就绪
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

                    LogUtils.info("开始读取数据");
                    ClientFile clientFile = new ClientFile();
                    FileOutputStream fout = new FileOutputStream(clientFile.getFile());

                    int num = -1;
                    while ((num = socketChannel.read(byteBuffer)) > 0) {
                        // 转成读的模式
                        byteBuffer.flip();

                        if (clientFile.getFileName() == null) {
                            if (byteBuffer.limit() < 4) {
                                continue;
                            }

                            // 文件名长度
                            clientFile.setFileNameLen(byteBuffer.getInt());
                            LogUtils.info("文件名长度：" + clientFile.getFileNameLen());

                            // 文件名
                            byte[] fileNameBytes = new byte[clientFile.getFileNameLen()];
                            byteBuffer.get(fileNameBytes);
                            clientFile.setFileName(new String(fileNameBytes));
                            LogUtils.info("文件名：" + clientFile.getFileName());

                            // 文件大小
                            clientFile.setFileSize(byteBuffer.getLong());
                            LogUtils.info("文件大小：" + clientFile.getFileSize());

                            long remain = Math.min(clientFile.getFileSize(), 1024);
                            byte[] fileContents = new byte[Integer.parseInt(String.valueOf(remain - 4 - clientFile.getFileName().getBytes().length - 8))];
                            byteBuffer.get(fileContents);
                            fout.write(fileContents);
                        }
                        else {
                            // 文件内容
                            byte[] fileContents = new byte[byteBuffer.limit()];
                            byteBuffer.get(fileContents);
                            fout.write(fileContents);
                        }
                        byteBuffer.clear();
                    }

                    if (num == -1) {
                        socketChannel.close();
                    }
                }
                selectionKeys.remove(selectionKey);
            }
        }

        LogUtils.info("服务端关闭连接");
        serverChannel.close();
    }
}
